<?php
###############   COPYLEFT GPLv3 LICENSE   ###############
##
## JFX Version 0.2.7
## Website Management Software
## www.jfxcms.com
##
## Copyright 2009 GPLv3 - http://www.opensource.org/licenses/gpl-3.0.html
##
## Anthony Gallon
## oi_antz@hotmail.com
##
## Permission is hereby granted to any person having a copy of this software
## to freely use and modify as required so long as the copyright notices
## and branding remain intact.
##
## Full license details available at http://www.jfxcms.com/license
##
###############   COPYLEFT GPLv3 LICENSE   ###############

class JFX_Block {

    public $elements = array();
    public $details = array(
        'id' => '',
        'parent_id' => '',
        'module_key' => '',
        'module_action' => '',
        'sorting' => '',
        'page_parent' => '',
        'class_name' => '',
        'ajax_enabled' => '',
        'is_droppable' => '',
        'page_id' => '',
        'exec_order' => '',
        'template' => '',
        'template_id' => '',
        'block_style' => '',
        'php_code' => '',
        'is_template' => 0,
        'template_script' => '',
        'template_style' => ''
    );
    public $id = '';
    public $parentid = '';
    public $pageid = '';
    public $workspaceid = '';
    public $moduleKey = '';
    public $moduleAction = '';
    public $object = NULL;
    public $title = 'New Block';
    public $defaultContent = '';
    
    public $saved = false;

    public function __construct(){
        
    }

    public function setClassName($className){
        $this->details['class_name'] = $className;

        if(is_object($this->object) && method_exists('setClassName', $this->object))
            $this->object->setClassName($className, $this->details);
    }

    public function getClassName(){
        $className = $this->details['class_name'];
        if(is_object($this->object) && method_exists('getClassName', $this->object))
            $className .= $this->object->getClassName($this->details);

        return $className;
    }

    public function setTemplate($template){
        if(is_object($this->object) && method_exists('setTemplate', $this->object))
            $template = $this->object->setTemplate($template, $this->details);
        $this->details['template'] = $template;
    }

    public function getTemplate(){
        return $this->details['template'];
    }

    public function setStyle($style){
        $this->details['block_style'] = $style;
    }

    public function delete(){
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        $LANG = JFX::registry('lang');
        foreach($this->elements as $k=>$v){
            $v->delete();
        };
        $id = explode('-', $this->id);
        $pageid = $id[2];
        $moduleKey = $id[4];
        $instanceid = $id[5];
        $params = array(
            'page_id' => $this->pageid,
            'workspace_id' => $this->workspaceid,
            'instance_id' => $instanceid
        );
        if(!is_object($this->object)) $this->loadObject();
        $this->object->delete($this->details);
        $DB->delete($CONFIG->dbprefix.'blocks', "id = '{$this->id}' AND workspace_id = '{$this->workspaceid}'");
        $LANG->deleteContent('core', 'block_title', $this->id, '*', $this->workspaceid);
    }

    public function clearCache(){
        $CACHE = JFX::registry('JFX_Block_Cache');
        $CACHE->clear($this->id.'_'.$this->workspaceid);
    }

    public function loadObject(){
        if($this->moduleKey == '') $this->moduleKey = 'content';
        if(!is_object($this->object)) $this->object = JFX::registry('JFX_Module_'.ucfirst(strtolower($this->moduleKey)));
        $this->object->setBlockId($this->id);
        return $this->object;
    }

    public function loadById($id, $workspaceid = '', $recursive = true, $loadObject = true){
        
        $JFXMemDebug[] = array('bytes'=>memory_get_usage(), 'file'=>__FILE__, 'line'=>__LINE__, 'time' => getmicrotime(), 'desc' => 'Before load by id '.$id);

        $DB = JFX::registry('db');
        $LANG = JFX::registry('lang');
        $USER = JFX::registry('JFX_User');
        $CONFIG = JFX::registry('config');

        if($workspaceid == '') $workspaceid = $USER->workspace;

        $id = $DB->escape($id);
        $details = $DB->fetchRow("SELECT * FROM {$CONFIG->dbprefix}blocks WHERE id = '{$id}' AND workspace_id = '{$workspaceid}'");
        
        if(!is_array($details) || count($details)==0) return false;

        $this->details = $details;
        $this->id = $details['id'];
        $this->parentid = $details['parent_id'];
        $this->moduleKey = $details['module_key'];
        $this->moduleAction = $details['module_action'];
        $this->workspaceid = $details['workspace_id'];
        $this->pageid = $details['page_id'];
        $this->saved = true;
        if($loadObject){
            $this->loadObject();
            $this->defaultContent = $this->object->getDefaultContent($this->moduleAction);
        }
        
        $this->title = $LANG->getContent('core', 'block_title', $this->id, '', $this->workspaceid);

        if($recursive){
            $els = array();

            $tmpEls = $DB->fetchAll("SELECT * FROM {$CONFIG->dbprefix}blocks WHERE parent_id = '{$id}' AND workspace_id = '{$workspaceid}' ORDER BY sorting ASC");
            if(!is_array($tmpEls)) $tmpEls = array();
            foreach($tmpEls as $k=>$v){
                $el = new JFX_Block;
                $el->loadById($v['id'], $workspaceid, $recursive, $loadObject);
                $els[] = $el;
            }
            $this->elements = $els;
        }else{
            $this->elements = array();
        }
        
        
        $JFXMemDebug[] = array('bytes'=>memory_get_usage(), 'file'=>__FILE__, 'line'=>__LINE__, 'time' => getmicrotime(), 'desc' => 'After load by id '.$id);

        return true;

    }

    public function prepare(){
        $SMARTY = JFX::registry('Smarty');

        $JFXMemDebug[] = array('bytes'=>memory_get_usage(), 'file'=>__FILE__, 'line'=>__LINE__, 'time' => getmicrotime(), 'desc' => 'Before prepare '.$this->id);


        $REG = JFX::registry('JFX_Block_Registry');
        $CACHE = JFX::registry('JFX_Block_Cache');

        $VIEW = JFX::registry('JFX_View');
        $SMARTY = JFX::registry('Smarty');
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        $USER = JFX::registry('JFX_User');
        $CRYPT = JFX::registry('JFX_Crypt');
        $LINK = JFX::registry('JFX_Link');
        $THEME = JFX::registry('JFX_Theme');
        $CORE = JFX::registry('JFX_Core');
        $SETTINGS = JFX::registry('JFX_Settings');


        if(false && $CACHE->isCached($this->id.'_'.$this->workspaceid)){
            $content = $CACHE->get($this->id.'_'.$this->workspaceid);
        }else{
            if(!is_object($this->object)) $this->loadObject();
            $tempid = $this->id;
            if(trim($this->details['template_id'])!=''){
                // its a template being mirrored
                $this->details['id'] = $this->details['template_id'];
                $content = $this->object->prepare($this->details);
            }else{
                // not a template being mirrored
                $content = $this->object->prepare($this->details);
            }
            
            if(strstr($this->details['template'], ':|content|:')!==false) $content = str_replace(':|content|:', $content, $this->details['template']);

            if($this->object->useCache($this->details)) $CACHE->set($this->id.'_'.$this->workspaceid, $content);
        }

        $content = JFX::fetchSmarty($content);

        $REG->register('render_'.$this->id, $content);


        $JFXMemDebug[] = array('bytes'=>memory_get_usage(), 'file'=>__FILE__, 'line'=>__LINE__, 'time' => getmicrotime(), 'desc' => 'After prepare '.$this->id);


    }

    public function render(){

        global $JFXMemDebug;

        $JFXMemDebug[] = array('bytes'=>memory_get_usage(), 'file'=>__FILE__, 'line'=>__LINE__, 'time' => getmicrotime(), 'desc' => 'Before render '.$this->id);


        $REG = JFX::registry('JFX_Block_Registry');

        $output = '
'/*<!-- start #'.$this->id.'-->*/.'
<div id="'.$this->id.'" class="'.$this->getClassName().'" style="'.$this->details['block_style'].'">
';
        if(!$REG->isRegistered('render_'.$this->id)){
            if(!is_object($this->object)) $this->loadObject();
            $this->prepare();
        }
        $output .= '    '.$REG->registry('render_'.$this->id).'
    ';
        
        foreach($this->elements as $k=>$v){
            $output .= '
'.$v->render().'
        ';
        }

        $output .= '
</div>
'/*<!-- end #'.$this->id.'-->*/.'

';

        $JFXMemDebug[] = array('bytes'=>memory_get_usage(), 'file'=>__FILE__, 'line'=>__LINE__, 'time' => getmicrotime(), 'desc' => 'After render '.$this->id);


        return $output;
    }

    public static function newModuleBlock($moduleKey, $moduleAction){
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        if(!JFX_Module::isValidModule($moduleKey)) return false;
        $block = new JFX_Block;
        $block->moduleKey = $moduleKey;
        $block->moduleAction = $moduleAction;
        $block->loadObject();
        $block->details = array_merge($block->details, $block->object->getDefaultDetails($moduleAction));
        return $block;
    }

    public function getDetails(){
        $details = $this->details;
        $details['default_content'] = $this->defaultContent;
        $details['title'] = $this->title;
        return $details;
    }

    public function save(){
        $DB = JFX::registry('db');
        $LANG = JFX::registry('lang');
        $CONFIG = JFX::registry('config');

        //$DB->debug(true);
        //$DB->showErrors(true);
        if($this->parentid == ''){
            JFX::addError('Block needs a parent id before it can be saved');
            return false;
        }
        if($this->pageid == ''){
            JFX::addError('Block needs a page id before it can be saved');
            return false;
        }
        if($this->id == ''){
            JFX::addError('Block needs an id before it can be saved');
            return false;
        }

        $numExistingBlocks = $DB->countRows($CONFIG->dbprefix.'blocks', "id = '{$this->id}' AND parent_id = '{$this->parentid}' AND workspace_id = '{$this->workspaceid}'");
        if($numExistingBlocks == 0){
            // first save, insert
            $DB->insert($CONFIG->dbprefix.'blocks', $this->details);
            $LANG->updateContent('core', 'block_title', $this->id, $this->title, '', $this->workspaceid);
        }else if($numExistingBlocks > 0){
            // updating
            $DB->update($CONFIG->dbprefix.'blocks', $this->details, "id = '{$this->id}' AND workspace_id = '{$this->workspaceid}' AND page_id = '{$this->pageid}'");
            /*
            echo '<pre>';
            var_dump($this->details);
            echo '</pre>';
             * 
             */
            $LANG->updateContent('core', 'block_title', $this->id, $this->title, '', $this->workspaceid);
        }

        foreach($this->elements as $k=>$el){
            $el->save();
        }

    }

    public function setRecursiveDetail($colname, $value){
        if(array_key_exists($colname, $this->details)) $this->details[$colname] = $value;
        if($colname == 'parent_id') $this->parentid = $value;
        if($colname == 'workspace_id') $this->workspaceid = $value;
        if($colname == 'module_action') $this->moduleAction = $value;
        if($colname == 'id') $this->id = $value;
        if($colname == 'page_id') $this->pageid = $value;
        foreach($this->elements as $k=>$v){
            if(is_object($v)) $this->elements[$k]->setRecursiveDetail($colname, $value);
        }
    }

    public function copy($newPageid, $newWorkspaceid){
        if($this->pageid != $newPageid || $this->workspaceid != $newWorkspaceid) $this->saved = false;
        $oldWorkspaceid = $this->workspaceid;
        $oldPageid = $this->pageid;
        $oldBlockid = $this->id;
        $this->workspaceid = $newWorkspaceid;
        $this->pageid = $newPageid;
        $this->details['page_id'] = $newPageid;
        $this->pageid = $newPageid;
        $this->workspaceid = $newWorkspaceid;
        $this->details['workspace_id'] = $newWorkspaceid;
        
        $ids = explode('-', $oldBlockid);
        $this->id = 'jfxpage-'.$newPageid.'-'.$ids[2].'-'.$ids[3];
        $this->details['id'] = $this->id;
        $pids = explode('-', $this->parentid);
        if(count($pids)>2) $this->parentid = 'jfxpage-'.$newPageid.'-'.$pids[2].'-'.$pids[3];
        else $this->parentid = 'jfxpage-'.$newPageid;
        $this->details['parent_id'] = $this->parentid;

        $this->save();
        foreach($this->elements as $k=>$v){
            if(is_object($v)) $this->elements[$k]->copy($newPageid, $newWorkspaceid);
        }
        if(!is_object($this->object)) $this->loadObject();
        $this->object->copyToNewBlock($oldBlockid, $this->id, $oldWorkspaceid, $newWorkspaceid);

    }

    public function setDetails($details){
        if(is_array($details)){
            if(array_key_exists('id', $details)){
                $this->id = $details['id'];
            }
            if(array_key_exists('parent_id', $details)){
                $this->parentid = $details['parent_id'];
                $this->details['parent_id'] = $details['parent_id'];
            }
            if(array_key_exists('page_id', $details)){
                $this->pageid = $details['page_id'];
                $this->details['page_id'] = $details['page_id'];
            }
            if(array_key_exists('workspace_id', $details)){
                $this->workspaceid = $details['workspace_id'];
                $this->details['workspace_id'] = $details['workspace_id'];
            }
            if(array_key_exists('pageid', $details)){
                $this->pageid = $details['page_id'];
                $this->details['page_id'] = $details['page_id'];
            }
            if(array_key_exists('module_key', $details)){
                $this->moduleKey = $details['module_key'];
            }
            if(array_key_exists('module_action', $details)){
                $this->moduleAction = $details['module_action'];
            }
            foreach($this->details as $k=>$v){
                if(array_key_exists($k, $details)) $this->details[$k] = $details[$k];
            }
            if(array_key_exists('title', $details)){
                $this->title = $details['title'];
            }
            return true;

        }else if(is_object($details)){
            if(isset($details->id)){
                $this->id = $details->id;
            }
            if(isset($details->parent_id)){
                $this->parentid = $details->parent_id;
                $this->details['parent_id'] = $details->parent_id;
            }
            if(isset($details->page_id)){
                $this->pageid = $details->page_id;
                $this->details['page_id'] = $details->page_id;
            }
            if(isset($details->workspace_id)){
                $this->workspaceid = $details->workspace_id;
                $this->details['workspace_id'] = $details->workspace_id;
            }
            if(isset($details->module_key)){
                $this->moduleKey = $details->module_key;
            }
            if(isset($details->pageid)){
                $this->pageid = $details->pageid;
                $this->details['page_id'] = $details->pageid;
            }
            if(isset($details->module_action)){
                $this->moduleAction = $details->module_action;
                $this->details['module_action'] = $details->module_action;
            }
            if(isset($details->title)){
                $this->title = $details->title;
            }
            foreach($this->details as $k=>$v){
                if(array_key_exists($k, $details)) $this->details[$k] = $details->$k;
            }

            return true;
        }else{
            return false;
        }

    }

    public function getElements(){
        $els = $this->elements;
        foreach($els as $k=>$v){
            //echo 'processing '.$v->id.'<br />';
            if(isset($v->object)){
                $els[$k]->object->ownerLicense = '';
                $els[$k]->object->publicLicense = '';
            }
            $els[$k]->elements = $els[$k]->getElements();
        }
        return $els;
    }

    public function getDetailsRecursive(){
        $details = $this->getDetails();
        $details['elements'] = array();
        $elements = $this->getElements();
        foreach($elements as $k=>$v){
            $block = new JFX_Block;
            $block->loadById($v->id);
            $blockEls = $block->getElements();
            if(count($blockEls)>0){
                $details['elements'][$k] = $block->getDetailsRecursive();
            }else{
                $details['elements'][$k] = array_merge($block->getDetails(), array('elements'=>$block->getElements()));
            }
        }
        return $details;
    }

    public function __toJson(){
        // recursive function
        $newEls = array();
        foreach($this->elements as $k=>$el) $newEls[$k] = $el->__toJson();
        $jsonString = '{
            "id" : "'.$this->id.'",
            "parentid" : "'.$this->parentid.'",
            "pageid" : "'.$this->pageid.'",
            "module_key" : "'.$this->moduleKey.'",
            "details" : {';
        $searches = array(
            '"',
            "\n",
            "\r"
        );
        $replacements = array(
            '\"',
            '\n',
            ''
        );
        foreach($this->details as $k=>$v){
                
                $v = str_replace($searches, $replacements, $v);
                $jsonString .=
                    '"'.$k.'" : "'.$v.'", ';
        }
        $jsonString .= '"title" : "'.$this->title.'"';
//        $jsonStringRev = strrev($jsonString);
//        if(substr($jsonStringRev, 0, 2)==' ,') $jsonStringRev = substr($jsonStringRev, 2);
//        $jsonString = strrev($jsonStringRev);

        $jsonString .= '}, ';
        
        if(count($newEls)>0) $jsonString .= '"elements": ['.implode(', ', $newEls).'], ';
        else $jsonString .= '"elements" : [], ';

        $jsonStringRev = strrev($jsonString);
        if(substr($jsonStringRev, 0, 2)==' ,') $jsonStringRev = substr($jsonStringRev, 2);
        $jsonString = strrev($jsonStringRev);
        $jsonString .= '}';


        return $jsonString;
    }



}